﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Web;

namespace Pay.Core.AlipayWap {
	public class PayApp {
		private Dictionary<string, string> PayInfo = new Dictionary<string, string>();
		/// <summary>
		/// APP支付
		/// </summary>
		/// <returns>The pay info.</returns>
		/// <param name="payment_query">Payment query.</param>
		/// <param name="body">Body.</param>
		/// <param name="pay_no">Pay no.</param>
		/// <param name="total_fee">Total fee.</param>
		/// <param name="notify_url">Notify URL.</param>
		public string GetPayInfo(payment_query payment_query, string body, string pay_no, decimal total_fee, string notify_url) {
			string orderInfo = GetOrderInfoWithOutEncode(payment_query.app_id, body, pay_no, total_fee, notify_url);
			// 对订单做RSA 签名
			string sign = RSAFromPkcs8.sign(orderInfo, payment_query.app_secret, "utf-8");
			//仅需对sign做URL编码
			sign = HttpUtility.UrlEncode(sign, Encoding.UTF8);
			string payInfo = GetOrderInfoWithEncode() + "&sign=" + sign;
			return payInfo;
		}
		/// <summary>
		/// 不包含Encode的字符串拼接
		/// </summary>
		/// <returns></returns>
		private string GetOrderInfoWithOutEncode(string app_id, string body, string pay_no, decimal total_fee, string notify_url) {
			PayInfo.Add("app_id", app_id);
			PayInfo.Add("biz_content", GetBizContent(total_fee.ToString(), body, pay_no));
			PayInfo.Add("charset", "utf-8");
			PayInfo.Add("format", "json");
			PayInfo.Add("method", "alipay.trade.app.pay");
			PayInfo.Add("notify_url", notify_url);
			PayInfo.Add("sign_type", "RSA");
			PayInfo.Add("timestamp", DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"));
			PayInfo.Add("version", "1.0");
			string strUrl = BuildQueryWithOutEncode(PayInfo);
			return strUrl;
		}
		/// <summary>
		/// 包含Encode的字符串拼接
		/// </summary>
		/// <returns></returns>
		private string GetOrderInfoWithEncode() {
			string strUrl = BuildQuery(PayInfo, "utf-8");
			return strUrl;
		}
		/// <summary>
		/// 获取支付内容详情
		/// </summary>
		/// <param name="total_amount"></param>
		/// <returns></returns>
		private string GetBizContent(string total_amount, string body, string pay_no) {
			Dictionary<string, string> biz_content_info = new Dictionary<string, string>();
			biz_content_info.Add("timeout_express", "30m");//该笔订单允许的最晚付款时间，逾期将关闭交易。
			biz_content_info.Add("seller_id", "");//收款支付宝用户ID。 如果该值为空，则默认为商户签约账号对应的支付宝用户ID
			biz_content_info.Add("product_code", "QUICK_MSECURITY_PAY");//销售产品码，商家和支付宝签约的产品码，为固定值QUICK_MSECURITY_PAY
			biz_content_info.Add("total_amount", total_amount);//订单总金额，单位为元，精确到小数点后两位，取值范围[0.01,100000000]
			biz_content_info.Add("subject", body);//商品的标题/交易标题/订单标题/订单关键字等。
			biz_content_info.Add("body", body);//对一笔交易的具体描述信息。如果是多种商品，请将商品描述字符串累加传给body。
			biz_content_info.Add("out_trade_no", pay_no);//商户网站唯一订单号
			string strBizContent = biz_content_info.ToJson();
			return strBizContent;
		}


		/// <summary>
		/// 组装普通文本请求参数(带Encode)。
		/// </summary>
		/// <param name="parameters">Key-Value形式请求参数字典</param>
		/// <returns>URL编码后的请求数据</returns>
		private string BuildQuery(IDictionary<string, string> parameters, string charset) {
			StringBuilder postData = new StringBuilder();
			bool hasParam = false;

			IEnumerator<KeyValuePair<string, string>> dem = parameters.GetEnumerator();
			while (dem.MoveNext()) {
				string name = dem.Current.Key;
				string value = dem.Current.Value;
				// 忽略参数名或参数值为空的参数
				if (!string.IsNullOrEmpty(name) && !string.IsNullOrEmpty(value)) {
					if (hasParam) {
						postData.Append("&");
					}

					postData.Append(name);
					postData.Append("=");

					string encodedValue = HttpUtility.UrlEncode(value, Encoding.GetEncoding(charset));

					postData.Append(encodedValue);
					hasParam = true;
				}
			}
			return postData.ToString();
		}
		/// <summary>
		/// 组装普通文本请求参数(不带Encode)。
		/// </summary>
		/// <param name="parameters">Key-Value形式请求参数字典</param>
		/// <returns>URL编码后的请求数据</returns>
		private string BuildQueryWithOutEncode(IDictionary<string, string> parameters) {
			StringBuilder postData = new StringBuilder();
			bool hasParam = false;

			IEnumerator<KeyValuePair<string, string>> dem = parameters.GetEnumerator();
			while (dem.MoveNext()) {
				string name = dem.Current.Key;
				string value = dem.Current.Value;
				// 忽略参数名或参数值为空的参数
				if (!string.IsNullOrEmpty(name) && !string.IsNullOrEmpty(value)) {
					if (hasParam) {
						postData.Append("&");
					}

					postData.Append(name);
					postData.Append("=");

					string encodedValue = value;
					postData.Append(encodedValue);
					hasParam = true;
				}
			}
			return postData.ToString();
		}
	}
}
